package com.tbit.uqbike.webmanager.util.adaPay;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.crypto.digest.mac.MacEngine;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huifu.adapay.Adapay;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.model.*;
import com.tbit.uqbike.constant.OperaPswConstant;
import com.tbit.uqbike.constant.ServiceUrlConstant;
import com.tbit.uqbike.constant.SubAccountConstant;
import com.tbit.uqbike.enums.AdapayCashType;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.AdaPayConfig;
import com.tbit.uqbike.object.pojo.AdaPayWithdrawalState;
import com.tbit.uqbike.object.pojo.SubAccount;
import com.tbit.uqbike.object.pojo.vo.SubAccountWithdrawalLogVO;
import com.tbit.uqbike.webmanager.dao.core.SubAccountDao;
import com.tbit.uqbike.webmanager.util.MD5PasswordUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 汇付支付工具类
 *
 * @Author:BUGTian
 * @DATE: 2022/5/24
 */
@Slf4j
public class AdaPayUtil {

    /**
     * adaPay的appId请求key
     */
    private static final String APP_ID_KEY = "app_id";

    /**
     * adaPay的商户id请求key
     */
    private static final String MEMBER_ID_KEY = "member_id";

    /**
     * 初始化聚合支付的配置
     */
    public static void initConfig(AdaPayConfig adaPayConfig) throws Exception {
        /**查询聚合支付的配置*/
        if (null == adaPayConfig) {
            throw new BaseException(SystemCodeEnum.ADAPAY_NOT_CONFIG);
        }
        /**初始化配置*/
        MerConfig merConfig = new MerConfig();
        merConfig.setApiKey(adaPayConfig.getApiKey());
        merConfig.setApiMockKey(adaPayConfig.getMockApiKey());
        merConfig.setRSAPrivateKey(adaPayConfig.getRsaPrivateKey());
        Adapay.initWithMerConfig(merConfig);
    }


    /**
     * 创建个人实名用户
     *
     * @param subAccount
     * @param adaPayConfig
     * @return
     * @throws BaseAdaPayException
     */
    public static boolean creatMember(SubAccount subAccount, AdaPayConfig adaPayConfig) throws BaseAdaPayException {
        Map<String, Object> memberParams = new HashMap<>(8);
        memberParams.put("adapay_func_code", "members.realname");
        memberParams.put(MEMBER_ID_KEY, subAccount.getMemberId());
        memberParams.put(APP_ID_KEY, adaPayConfig.getAppId());
        memberParams.put("tel_no", subAccount.getPhone());
        memberParams.put("user_name", subAccount.getUserName());
        memberParams.put("cert_type", subAccount.getCardType());
        memberParams.put("cert_id", subAccount.getCardNumber());
        Map<String, Object> member = AdapayCommon.requestAdapay(memberParams);
        if (SubAccountConstant.SUCCESS_MEMBER.equals(member.get("identified"))) {
            return true;
        }
        return false;
    }

    /**
     * 对私创建结算账户
     *
     * @param subAccount
     * @param adaPayConfig
     * @return
     */
    public static String createSettleAccount(SubAccount subAccount, AdaPayConfig adaPayConfig) throws BaseAdaPayException {
        Map<String, Object> settleCountParams = new HashMap<>(4);
        Map<String, Object> accountInfo = new HashMap<>(8);
        accountInfo.put("card_id", subAccount.getBankCardNumber());
        accountInfo.put("card_name", subAccount.getUserName());
        accountInfo.put("cert_id", subAccount.getCardNumber());
        accountInfo.put("cert_type", subAccount.getCardType());
        accountInfo.put("tel_no", subAccount.getPhone());
        //银行账户类型：1-对公；2-对私
        accountInfo.put("bank_acct_type", "2");
        settleCountParams.put(MEMBER_ID_KEY, subAccount.getMemberId());
        settleCountParams.put(APP_ID_KEY, adaPayConfig.getAppId());
        //目前仅支持：bank_account（银行卡）
        settleCountParams.put("channel", "bank_account");
        settleCountParams.put("account_info", accountInfo);
        Map<String, Object> settleCount = SettleAccount.create(settleCountParams);
        Object errorMsg = settleCount.get("error_msg");
        if (StringUtils.isEmpty(errorMsg)) {
            //成功创建
            return SubAccountConstant.SUCCESS_SETTLE_ACCOUNT;
        }
        return errorMsg.toString();
    }

    /**
     * 创建企业用户对象（自动开结算账户）
     *
     * @param subAccount
     * @param adaPayConfig
     * @param frontIdCardPhoto        法人身份证正面照
     * @param reverseIdCardPhoto      法人身份证反面照
     * @param openBankPermissionPhoto 开户银行许可证照
     * @return
     * @throws BaseAdaPayException
     */
    public static boolean createCorpMember(SubAccount subAccount, AdaPayConfig adaPayConfig, MultipartFile frontIdCardPhoto, MultipartFile reverseIdCardPhoto, MultipartFile openBankPermissionPhoto) throws BaseAdaPayException {
        Map<String, Object> memberParams = new HashMap<String, Object>(16);
        memberParams.put(MEMBER_ID_KEY, subAccount.getMemberId());
        memberParams.put(APP_ID_KEY, adaPayConfig.getAppId());
        memberParams.put("order_no", String.format("%s_%s", "order", subAccount.getMemberId()));
        memberParams.put("social_credit_code_expires", subAccount.getCompanyCodeValidity());
        memberParams.put("business_scope", subAccount.getBusinessScope());
        memberParams.put("name", subAccount.getCompanyName());
        memberParams.put("prov_code", subAccount.getProvinceCode());
        memberParams.put("area_code", subAccount.getAreaCode());
        memberParams.put("social_credit_code", subAccount.getCompanyCode());
        memberParams.put("legal_person", subAccount.getUserName());
        memberParams.put("legal_cert_id", subAccount.getCardNumber());
        memberParams.put("legal_cert_id_expires", subAccount.getCardNumberValidity());
        memberParams.put("legal_mp", subAccount.getPhone());
        memberParams.put("address", subAccount.getCompanyAddress());
        //银行代码，需要自动开结算账户，本字段必填
        memberParams.put("bank_code", subAccount.getBankCode());
        memberParams.put("bank_acct_type", "1");
        memberParams.put("card_no", subAccount.getBankCardNumber());
        memberParams.put("card_name", subAccount.getCompanyName());
        //图片压缩并上传
        File file = toZip(frontIdCardPhoto, reverseIdCardPhoto, openBankPermissionPhoto);
        Map<String, Object> member = CorpMember.create(memberParams, file);
        if (member == null) {
            return false;
        }
        if (Objects.equals(member.get("status"), "failed")) {
            Object errorMsg = member.get("error_msg");
            if (errorMsg == null) {
                errorMsg = "开户失败！请检查录入的信息是否有误！";
            }
            log.error("====对公创建账户失败====，请求参数为:" + JSON.toJSONString(memberParams) + "，汇付平台返回参数为:" + JSON.toJSONString(member));
            throw new BaseException(errorMsg.toString());
        }
        return true;
    }

    /**
     * 调用客户端接口进行退款
     *
     * @param userId       用户id
     * @param refundMoney  退款金额
     * @param rechargeType 充值类型
     * @param orderNO      骑行订单号
     * @param rechargeNO   订单编号
     * @return
     */
    public static Integer refund(Integer userId, Integer refundMoney, Integer rechargeType, String orderNO, String rechargeNO) {
        String url = OperaPswConstant.ACCOUNT_OPERA_PUSH_URL + ServiceUrlConstant.CLIENT_RETURN_MONEY;
        long date = System.currentTimeMillis();
        String param = "youqu";
        String sign = MD5PasswordUtil.MD5("TBIT" + date + param);
        Map<String, Object> paramMap = new HashMap<>(8);
        paramMap.put("userId", userId);
        paramMap.put("money", refundMoney);
        paramMap.put("date", date);
        paramMap.put("param", param);
        paramMap.put("sign", sign);
        //免押卡、骑行卡、vip会员卡、优惠券套餐、需要传充值单号   骑行订单传骑行订单号
        if (!StringUtils.isEmpty(orderNO)) {
            rechargeNO = orderNO;
            paramMap.put("buyOrderNO", rechargeNO);
        }
        switch (rechargeType) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                paramMap.put("buyOrderNO", rechargeNO);
                break;
            default:
                break;
        }
        HttpResponse response = HttpRequest.get(url).form(paramMap).execute();
        log.info("=================调用客户端接口退款===================");
        log.info(String.format("请求参数：%s", JSON.toJSONString(paramMap)));
        JSONObject jsonObject = JSON.parseObject(response.body());
        Object data = jsonObject.get("data");
        log.info(JSON.toJSONString(jsonObject));
        if (!Objects.isNull(data)) {
            //返回已退款金额
            return Double.valueOf(data.toString()).intValue();
        }
        return 0;
    }

    /**
     * 查询企业用户对象
     *
     * @param subAccount
     * @param adaPayConfig
     * @return
     * @throws BaseAdaPayException
     */
    public static Map<String, Object> queryCorpMember(SubAccount subAccount, AdaPayConfig adaPayConfig) throws BaseAdaPayException {
        Map<String, Object> memberParams = new HashMap<String, Object>(2);
        memberParams.put(MEMBER_ID_KEY, subAccount.getMemberId());
        memberParams.put(APP_ID_KEY, adaPayConfig.getAppId());
        Map<String, Object> member = CorpMember.query(memberParams);
        return member;
    }

    /**
     * 查询账户余额
     *
     * @return 金额，单位分
     * @throws BaseAdaPayException
     */
    public static Integer querySubAccountBalance(SubAccount subAccount, AdaPayConfig adaPayConfig) throws BaseAdaPayException {
        Map<String, Object> queryParams = new HashMap<>(4);
        queryParams.put(MEMBER_ID_KEY, subAccount.getMemberId());
        queryParams.put(APP_ID_KEY, adaPayConfig.getAppId());
        Map<String, Object> settleCount = SettleAccount.balance(queryParams);
        if ("succeeded".equals(settleCount.get("status"))) {
            //可用余额，单元元
            Double avlBalance = Double.valueOf(settleCount.get("avl_balance").toString());
            return (int) (avlBalance * 100);
        }
        return 0;
    }

    /**
     * 提现
     *
     * @param subAccount
     * @param adaPayConfig
     * @param money        提现金额，单位元  格式 1.00
     * @throws BaseAdaPayException
     */
    public static String withdrawal(SubAccount subAccount, AdaPayConfig adaPayConfig, String money, AdapayCashType cashType, String remark) throws BaseAdaPayException {
        String withdrawalOrderNo = IdUtil.simpleUUID();
        Map<String, Object> cashParam = new HashMap<String, Object>(8);
        cashParam.put("order_no", withdrawalOrderNo);
        cashParam.put(APP_ID_KEY, adaPayConfig.getAppId());
        cashParam.put("cash_type", cashType.code);
        cashParam.put("cash_amt", money);
        cashParam.put("remark", remark);
        cashParam.put(MEMBER_ID_KEY, subAccount.getMemberId());
        Map<String, Object> cash = Drawcash.create(cashParam);
        Object status = cash.get("status");
        /*
        pending =交易处理中
        succeeded = 交易成功
        failed = 交易失败
         */
        log.info(JSON.toJSONString(cash));
        if (!Objects.equals(status, "failed")) {
            log.info("交易成功, 参数: {}", cashParam);
            return withdrawalOrderNo;
            //交易成功
        }
        log.error("交易失败，失败内容" + JSON.toJSONString(cash));
        return null;
    }


    public static Integer queryWithdrawalState(SubAccountWithdrawalLogVO subAccountWithdrawalLogVO, AdaPayConfig adaPayConfig) {
        Map<String, Object> queryCashParam = new HashMap<String, Object>(2);
        queryCashParam.put("order_no", subAccountWithdrawalLogVO.getWithdrawalOrderNO());
        Map<String, Object> drawcash = new HashMap<>();
        try {
            drawcash = Drawcash.query(queryCashParam);
        } catch (BaseAdaPayException e) {
            log.error(e.getMessage(), e);
        }
        AdaPayWithdrawalState adaPayWithdrawalState;
        try {
            adaPayWithdrawalState = JSON.parseObject(JSON.toJSONString(drawcash), AdaPayWithdrawalState.class);
        } catch (Exception e) {
            return null;
        }
        if ("succeeded".equals(adaPayWithdrawalState.getStatus())) {
            String stat = adaPayWithdrawalState.getCash_list().get(0).getTrans_stat();
            switch (stat) {
                case "S":
                    //成功
                    return SubAccountConstant.WITHDRAWAL_SUCCESS;
                case "F":
                    //失败
                    return SubAccountConstant.WITHDRAWAL_ERROR;
                case "P":
                    //处理中
                    return SubAccountConstant.WITHDRAWAL_ING;
                default:
                    break;
            }
        }
        return null;
    }


    /**
     * 将MultipartFile转换为File
     *
     * @param multiFile
     * @return
     */
    public static File MultipartFileToFile(MultipartFile multiFile) {
        //获取文件名
        String fileName = multiFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 若须要防止生成的临时文件重复,能够在文件名后添加随机码

        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 图片压缩
     *
     * @param frontIdCardPhoto
     * @param reverseIdCardPhoto
     * @param openBankPermissionPhoto
     * @return
     */
    public static File toZip(MultipartFile frontIdCardPhoto, MultipartFile reverseIdCardPhoto, MultipartFile openBankPermissionPhoto) {
        File zip = new File(OperaPswConstant.PATH + "/contraryZip/" + System.currentTimeMillis() + "reviewData.zip");
        File zipFile = ZipUtil.zip(zip, false, MultipartFileToFile(frontIdCardPhoto), MultipartFileToFile(reverseIdCardPhoto), MultipartFileToFile(openBankPermissionPhoto));
        return zipFile;
    }

    /**
     * 修改卡号
     *
     * @param
     * @return
     */
    public static String updateBankCard(SubAccount subAccount, AdaPayConfig adaPayConfig,String bankCardNumber) throws BaseAdaPayException {
/*        Map<String, Object> settleAccountIdMap = new  HashMap<String, Object>(2);
        settleAccountIdMap.put("app_id", adaPayConfig.getAppId());
        Map<String, Object> member = Member.queryList(settleAccountIdMap);
        Object membersObj = member.get("members");
        // 获取 "members" 字段的值
        String settle_account_id = getSettleAccountId(subAccount, membersObj);
        //删除
        HashMap<String, Object> deleteHashMap = new HashMap<>();
        deleteHashMap.put("settle_account_id", settle_account_id);
        deleteHashMap.put("member_id", subAccount.getMemberId());
        deleteHashMap.put("app_id", adaPayConfig.getAppId());
        Map<String, Object> deleteCount = SettleAccount.delete(deleteHashMap);
        if (Objects.equals("failed",deleteCount.get("status"))){
            return  JSONObject.toJSONString(deleteCount);
        }*/
        //新增
        Map<String, Object> settleCountParams = new  HashMap<String, Object>(4);
        Map<String, Object> accountInfo = new  HashMap<String, Object>(9);
        accountInfo.put("card_id",bankCardNumber);
        accountInfo.put("card_name",subAccount.getNickName());
        accountInfo.put("cert_id",subAccount.getCardNumber());
        accountInfo.put("cert_type",subAccount.getCardType());
        accountInfo.put("tel_no",subAccount.getPhone());
        accountInfo.put("bank_code",subAccount.getBankCode());
        accountInfo.put("bank_acct_type","1");
        accountInfo.put("prov_code",subAccount.getProvinceCode());
        accountInfo.put("area_code",subAccount.getAreaCode());
        settleCountParams.put("member_id", subAccount.getMemberId());
        settleCountParams.put("app_id",  adaPayConfig.getAppId());
        settleCountParams.put("channel","bank_account");
        settleCountParams.put("account_info", accountInfo);
        Map<String, Object> settleCount = SettleAccount.create(settleCountParams);
        if (Objects.equals("failed",settleCount.get("status"))){
            //如果修改失败,保持原卡号不变
            accountInfo.put("card_id",subAccount.getBankCardNumber());
            Map<String, Object> settleCount1 = SettleAccount.create(settleCountParams);
            return  JSONObject.toJSONString(settleCount);
        }
        return "true";
    }


    /**
     * 修改卡号
     *
     * @param
     * @return
     */
    public static String selectBankCard(SubAccount subAccount, AdaPayConfig adaPayConfig) throws BaseAdaPayException {
        Map<String, Object> settleAccountIdMap = new  HashMap<String, Object>(2);
        settleAccountIdMap.put("app_id", adaPayConfig.getAppId());
        Map<String, Object> member = Member.queryList(settleAccountIdMap);
        Object membersObj = member.get("members");
        // 获取 "members" 字段的值
        String settle_account_id = getSettleAccountId(subAccount, membersObj);
        Map<String, Object> settleCountParams = new  HashMap<String, Object>(3);
        settleCountParams.put("settle_account_id", settle_account_id);
        settleCountParams.put("member_id", subAccount.getMemberId());
        settleCountParams.put("app_id", adaPayConfig.getAppId());
        Map<String, Object> settleCount = SettleAccount.query(settleCountParams);
        Map<String, Object> accountInfo = (Map<String, Object>) settleCount.get("account_info");
        return (String) accountInfo.get("card_id");
    }


    /**
     * 获取settle_account_id
     *
     * @param
     * @return
     */
    private static String getSettleAccountId(SubAccount subAccount, Object membersObj) {
        String settle_account_id;
        if (membersObj instanceof List) {
            List<Object> membersList = (List<Object>) membersObj;
            // 遍历列表中的每个元素
            for (Object obj : membersList) {
                if (obj instanceof Map) {
                    Map<String, Object> memberMap = (Map<String, Object>) obj;
                    // 获取嵌套的列表
                    if (subAccount.getMemberId().equals(memberMap.get("member_id"))) {
                        Object nestedListObj = memberMap.get("settle_accounts");
                        if (nestedListObj instanceof List) {
                            List<Object> nestedList = (List<Object>) nestedListObj;
                            // 在嵌套列表中查找满足条件的 id
                            for (Object nestedObj : nestedList) {
                                if (nestedObj instanceof Map) {
                                    Map<String, Object> nestedMap = (Map<String, Object>) nestedObj;
                                    if (subAccount.getMemberId().equals(nestedMap.get("member_id"))) {
                                        // 检查是否满足条件
                                        // 这里假设满足条件的对象具有 id 大于 2 的情况
                                        settle_account_id = (String)nestedMap.get("id");
                                        return settle_account_id;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return "";
    }

}
